package lollab

import (
	"bytes"
	"crypto/md5"
	"encoding/json"
	"errors"
	"fmt"
	"hash"
	"net/http"
	"net/url"
	"strings"
)

type Lollab struct {
	Client_id          string
	Client_secret      string
	Request_public_key string
	Scope              string
	Grant_type         string

	client *http.Client

	//加密的计算方式
	hex hash.Hash

	//服务器token信息
	access_token, token_type string
	expires_in               int64
}

const (
	//访问方式
	ACCESS_POST = "POST"
	ACCESS_GET  = "GET"

	//header设置
	CONTENT_TYPE = "multipart/form-data"

	//访问地址
	URL_API   = "https://a1-s-point.lollab.co/api"
	URL_TOKEN = "https://a1-s-point.lollab.co/api/token"
)

func (l *Lollab) Api() (string, error) {
	form := url.Values{
		"client_id":          {l.Client_id},
		"client_secret":      {l.Client_secret},
		"request_public_key": {l.Request_public_key},
	}

	return l.req(form, URL_API, ACCESS_GET)
}

func (l *Lollab) Token() (string, error) {
	form := url.Values{
		"client_id":     {l.Client_id},
		"client_secret": {l.Client_secret},
		"grant_type":    {l.Grant_type},
		"scope":         {l.Scope},
	}
	str, err := l.req(form, URL_TOKEN, ACCESS_POST)
	if err != nil {
		return "", err
	}

	//解析
	res := make(map[string]interface{})
	err = json.Unmarshal([]byte(str), &res)
	if err != nil {
		return "", err
	}

	//如果有ack说明请求失败则返回失败的信息
	if _, ok := res["ack"]; ok {
		return "", errors.New(str)
	}

	if val, ok := res["access_token"]; ok {
		if str_val, str_ok := val.(string); str_ok {
			l.access_token = str_val
		}
	}
	if val, ok := res["token_type"]; ok {
		if str_val, str_ok := val.(string); str_ok {
			l.token_type = str_val
		}
	}
	if val, ok := res["expires_in"]; ok {
		if int_val, int_ok := val.(int64); int_ok {
			l.expires_in = int_val
		}
	}

	// l.token_type = (string)res["token_type"]
	// l.expires_in = (int64)res["expires_in"]
	//TODO:加个定时器用于定时执行更新token的信息
	fmt.Println(fmt.Sprintf("%+v", l))

	return str, nil
}

func (l *Lollab) req(form url.Values, url, method string) (string, error) {
	body := strings.NewReader(form.Encode())

	req, err := http.NewRequest(method, url, body)
	if err != nil {
		return "", err
	}
	req.Header.Set("Content-Type", CONTENT_TYPE)
	res, err := l.doRes(req)
	if err != nil {
		return "", err
	}

	res_body := &bytes.Buffer{}
	_, err = res_body.ReadFrom(res.Body)
	if err != nil {
		return "", err
	}
	res.Body.Close()
	return res_body.String(), nil
}

func (l *Lollab) doRes(req *http.Request) (*http.Response, error) {
	if l.client == nil {
		l.client = &http.Client{}
	}
	return l.client.Do(req)
}

var DefaultLollab = &Lollab{
	Grant_type:         "client_credentials",
	Client_id:          "Exorcism-Union",
	Client_secret:      "PjyQ8wetz9zcB432",
	Scope:              "member/account,member/token,member/checkout",
	Request_public_key: "5az7ryu4nf6c08su",
	hex:                md5.New(),
}
